﻿using System;
using System.Activities;
using System.Activities.Validation;
using System.Activities.XamlIntegration;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Threading;
using System.Xaml;
using Common.Activities;

namespace Common
{
    public static class Helper
    {
        public static void MarshalToUiThread(Action func)
        {
            Application.Current.Dispatcher.Invoke(func, DispatcherPriority.Normal);
        }

        private static List<ActivityDescriptor> _activityList;

        public static List<ActivityDescriptor> ActivityList
        {
            get
            {
                if (_activityList == null)
                    LoadActivities();
                
                return _activityList;
            }
        }

        public static void LoadActivities(string path = default(string))
        {
            if (path == default(string))
            {
                path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                
                if (path == null) return;
                
                path = Path.Combine(path, "Automations");
            }
            _activityList = new List<ActivityDescriptor>();
            _activityList.Add(new ActivityDescriptor() {Name = "Select Activity", Xaml = null});

            IEnumerable<string> filePaths = Directory.GetFiles(path, "*.xaml");
            foreach (var filePath in filePaths)
            {
                _activityList.Add(new ActivityDescriptor()
                                      {Name = Path.GetFileNameWithoutExtension(filePath), Xaml = File.ReadAllText(filePath)});
            }
        }

        public static bool TryLoadAndValidateActivity(string xaml, out System.Activities.Activity program)
        {
            program = null;

            Exception loadException = null;

            try
            {
                using (var reader = new StringReader(xaml))
                {
                    var activityType =
                        Type.GetType(
                            "Common.Activities.UserStepSequence,Common");
                    var settings = new XamlXmlReaderSettings { LocalAssembly = activityType.Assembly };

                    using (var xamlReader = new XamlXmlReader(reader, settings))
                    {
                        program = ActivityXamlServices.Load(xamlReader);
                    }
                }
            }
            catch (Exception ex)
            {
                loadException = ex;
            }

            ValidationResults results = null;
            if (loadException != null && program != null)
            {
                //If this is a Dynamic activity - a XamlException might occur
                try
                {
                    results = ActivityValidationServices.Validate(program);
                }
                catch (XamlException xamlException)
                {
                    loadException = xamlException;
                }
            }

            if (loadException != null)
            {
                //WriteException(loadException, "An error has occured loading the specified file: " + originalPath);
                return false;
            }

            return true;
        }

        public static void InspectActivity(Activity root, ObservableCollection<UserStepActivity> steps, ref UserStepSequence rootSequenceActivity)
        {
            // Inspect the activity tree using WorkflowInspectionServices.
            IEnumerator<Activity> activities =
            WorkflowInspectionServices.GetActivities(root).GetEnumerator();

            while (activities.MoveNext())
            {
                var userStep = activities.Current as UserStepActivity;
                if (userStep != null)
                {
                    // we only care about the user steps, actually
                    steps.Add(userStep);
                }
                else
                {
                    var userStepSequence = activities.Current as UserStepSequence;
                    if (userStepSequence != null)
                    {
                        rootSequenceActivity = userStepSequence;
                    }


                    InspectActivity(activities.Current, steps, ref rootSequenceActivity);
                }
            }
        }

        // TODO: genericize, or figure out context issue?
        public static bool ConvertArgumentToBool(InArgument<bool> argument)
        {
            return bool.Parse(argument.Expression.ToString());
        }
    }
}
